package com.ssy.lingxi.marketing.serviceimpl.base.activity;

import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.marketing.entity.activity.ActivityGoodsDO;
import com.ssy.lingxi.marketing.entity.activity.MerchantActivityDO;
import com.ssy.lingxi.marketing.model.constant.*;
import com.ssy.lingxi.marketing.model.vo.activity.request.MerchantActivityCommonPageVO;
import com.ssy.lingxi.marketing.model.vo.activity.request.MerchantActivityPlatformPageVO;
import com.ssy.lingxi.marketing.repository.ActivityGoodsRepository;
import com.ssy.lingxi.marketing.repository.MerchantActivityRepository;
import com.ssy.lingxi.marketing.service.IProcessFeignService;
import com.ssy.lingxi.marketing.utils.NumberUtil;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 基础商家活动服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/8/16
 */
@Slf4j
@Service
public class BaseMerchantActivityService extends BaseActivityService {

    @Resource
    private IProcessFeignService processFeignService;
    @Resource
    private ActivityGoodsRepository goodsRepository;
    @Resource
    private MerchantActivityRepository merchantActivityRepository;
    @Resource
    private BaseActivityRecordService activityRecordService;

    /**
     * 判断活动时间
     * @param currentTimeMillis 当前时间
     * @param startTime 活动开始时间
     * @param endTime 活动结束时间
     * @return 返回结果
     */
    protected Wrapper<Void> checkMerchantActivityTime(Long currentTimeMillis, Long startTime, Long endTime) {
        return this.checkActivityTime(currentTimeMillis, startTime, endTime);
    }

    /**
     * 商家活动公共分页列表
     *
     * @param loginUser       登录用户信息
     * @param pageVO          接口参数
     * @param outerStatus 外部状态
     * @param innerStatus 内部状态
     * @return 返回结果
     */
    protected Page<MerchantActivityDO> baseMerchantActivityPage(UserLoginCacheDTO loginUser, MerchantActivityCommonPageVO pageVO, Integer outerStatus, Integer innerStatus) {
        // 组装查询条件
        Specification<MerchantActivityDO> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            list.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            /*22.1.20版废弃
            // 组装外部状态条件
            if (NumberUtil.notNullOrZero(outerStatus)) {
                list.add(cb.equal(root.get("outerStatus"), outerStatus));
            }*/

            // 组装内部状态条件
            if (NumberUtil.notNullOrZero(innerStatus)) {
                list.add(cb.equal(root.get("innerStatus"), innerStatus));
            }

            if (StringUtils.isNotEmpty(pageVO.getStartTime())) {
                Long startTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateStart(pageVO.getStartTime()));
                list.add(cb.greaterThan(root.get("startTime").as(Long.class), startTime));
            }
            if (StringUtils.isNotEmpty(pageVO.getEndTime())) {
                Long endTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateEnd(pageVO.getEndTime()));
                list.add(cb.lessThan(root.get("endTime").as(Long.class), endTime));
            }
            if (StringUtils.isNotEmpty(pageVO.getActivityName())) {
                list.add(cb.like(root.get("activityName").as(String.class), "%" + pageVO.getActivityName().trim() + "%"));
            }
            if (Objects.nonNull(pageVO.getId())) {
                list.add(cb.equal(root.get("id").as(Long.class), pageVO.getId()));
            }
            if (Objects.nonNull(pageVO.getActivityType())) {
                list.add(cb.equal(root.get("activityType").as(Integer.class), pageVO.getActivityType()));
            }

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("startTime").descending());

        return merchantActivityRepository.findAll(spec, page);
    }

    /**
     * 商家活动公共分页列表
     *
     * @param loginUser       登录用户信息
     * @param pageVO          接口参数
     * @return 返回结果
     */
    protected Page<MerchantActivityDO> baseToBeSubmitActivityMerchantActivityPage(UserLoginCacheDTO loginUser, MerchantActivityCommonPageVO pageVO) {

        //22.1.20版废弃 List<Integer> outerStatusList = Arrays.asList(MerchantActivityOuterStatusEnum.TO_BE_SUBMIT.getCode(), MerchantActivityOuterStatusEnum.NOT_PASSED.getCode());
        List<Integer> innerStatusList = Arrays.asList(MerchantActivityInnerStatusEnum.TO_BE_SUBMIT_EXAM.getCode(), MerchantActivityInnerStatusEnum.EXAMINE_NO_PASS_1.getCode(), MerchantActivityInnerStatusEnum.EXAMINE_NO_PASS_2.getCode());

        // 组装查询条件
        Specification<MerchantActivityDO> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            list.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));

            // 组装状态条件
            list.add(cb.in(root.get("innerStatus")).value(innerStatusList));
            /*22.1.20版废弃
            Predicate andP = cb.and(cb.equal(root.get("outerStatus"), MerchantActivityOuterStatusEnum.TO_BE_SUBMIT.getCode()), cb.in(root.get("innerStatus")).value(innerStatusList));
            Predicate orP = cb.or(andP, cb.equal(root.get("outerStatus"), MerchantActivityOuterStatusEnum.NOT_PASSED.getCode()));
            list.add(orP);*/

            if (StringUtils.isNotEmpty(pageVO.getStartTime())) {
                Long startTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateStart(pageVO.getStartTime()));
                list.add(cb.greaterThan(root.get("startTime").as(Long.class), startTime));
            }
            if (StringUtils.isNotEmpty(pageVO.getEndTime())) {
                Long endTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateEnd(pageVO.getEndTime()));
                list.add(cb.lessThan(root.get("endTime").as(Long.class), endTime));
            }
            if (StringUtils.isNotEmpty(pageVO.getActivityName())) {
                list.add(cb.like(root.get("activityName").as(String.class), "%" + pageVO.getActivityName().trim() + "%"));
            }
            if (Objects.nonNull(pageVO.getId())) {
                list.add(cb.equal(root.get("id").as(Long.class), pageVO.getId()));
            }
            if (Objects.nonNull(pageVO.getActivityType())) {
                list.add(cb.equal(root.get("activityType").as(Integer.class), pageVO.getActivityType()));
            }

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("startTime").descending());

        return merchantActivityRepository.findAll(spec, page);
    }

    /**
     * 平台查询商家活动公共分页列表
     *
     * @param loginUser       登录用户信息
     * @param pageVO          接口参数
     * @param outerStatus 外部状态
     * @return 返回结果
     */
    protected Page<MerchantActivityDO> basePlatformMerchantActivityPage(UserLoginCacheDTO loginUser, MerchantActivityPlatformPageVO pageVO, Integer outerStatus) {
        // 组装查询条件
        Specification<MerchantActivityDO> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            // 组装外部状态条件
            if (Objects.nonNull(outerStatus)) {
                list.add(cb.equal(root.get("outerStatus"), outerStatus));
            }

            if (Objects.nonNull(pageVO.getId())) {
                list.add(cb.equal(root.get("id").as(Long.class), pageVO.getId()));
            }

            if (Objects.nonNull(pageVO.getActivityType())) {
                list.add(cb.equal(root.get("activityType").as(Integer.class), pageVO.getActivityType()));
            }

            if (StringUtils.isNotEmpty(pageVO.getStartTime())) {
                Long startTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateStart(pageVO.getStartTime()));
                list.add(cb.greaterThan(root.get("startTime").as(Long.class), startTime));
            }

            if (StringUtils.isNotEmpty(pageVO.getEndTime())) {
                Long endTime = DateTimeUtil.toMilliSecond(DateTimeUtil.parseDateEnd(pageVO.getEndTime()));
                list.add(cb.lessThan(root.get("endTime").as(Long.class), endTime));
            }

            if (StringUtils.isNotEmpty(pageVO.getActivityName())) {
                list.add(cb.like(root.get("activityName").as(String.class), "%" + pageVO.getActivityName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getMemberName())) {
                list.add(cb.like(root.get("memberName").as(String.class), "%" + pageVO.getMemberName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        };

        // 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("startTime").descending());

        return merchantActivityRepository.findAll(spec, page);
    }

    /**
     * 待审核商家营销活动 - 审核
     * @param loginUser 登录用户信息
     * @param merchantActivityDOList 商家活动
     * @param agree 是否审核通过
     */
    protected void baseExamine(UserLoginCacheDTO loginUser, List<MerchantActivityDO> merchantActivityDOList, Integer agree) {
        for (MerchantActivityDO merchantActivityDO : merchantActivityDOList) {
            /*22.1.20版废弃
            // 执行外部流转
            TaskExecuteVO taskStartVO = new TaskExecuteVO();
            taskStartVO.setProcessKey(merchantActivityDO.getOuterProcessKey());
            taskStartVO.setMemberId(loginUser.getMemberId());
            taskStartVO.setRoleId(loginUser.getMemberRoleId());
            taskStartVO.setDataId(merchantActivityDO.getId());
            taskStartVO.setAgree(agree);
            taskStartVO.setTaskId(merchantActivityDO.getOuterTaskId());
            Wrapper<SimpleTaskCompleteVO> outerResult = processFeignService.completeSimpleTask(taskStartVO);
            if (outerResult.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }
            merchantActivityDO.setOuterTaskId(outerResult.getData().getTaskId());
            merchantActivityDO.setOuterTaskStep(outerResult.getData().getStep());
            merchantActivityDO.setOuterStatus(outerResult.getData().getStatus());*/

            // 内部状态
            if (CommonBooleanEnum.YES.getCode().equals(agree)){
                //Integer innerStatus = Optional.ofNullable(outerResult.getData().getProperties().get("inner")).map(Integer::valueOf).orElse(MerchantActivityInnerStatusEnum.TO_BE_ONLINE.getCode());
                //merchantActivityDO.setInnerStatus(innerStatus);
            } else {
                // 不通过内部重新走流程
                // 启动内部流程
                SimpleTaskCompleteVO innerTask = processFeignService.startSimpleProcess(merchantActivityDO.getMemberId(), merchantActivityDO.getRoleId(), MarketingConstants.merchant_activity_inner_key, merchantActivityDO.getId());
                merchantActivityDO.setInnerProcessKey(MarketingConstants.merchant_activity_inner_key);
                merchantActivityDO.setInnerTaskId(innerTask.getTaskId());
                merchantActivityDO.setInnerTaskStep(innerTask.getStep());
            }
            merchantActivityRepository.saveAndFlush(merchantActivityDO);

            // 活动商品审核状态
            if (CommonBooleanEnum.YES.getCode().equals(agree)) {
                List<ActivityGoodsDO> activityGoodsDOList = goodsRepository.findByBelongTypeAndActivityId(BelongTypeEnum.MERCHANT.getCode(), merchantActivityDO.getId());
                if (!CollectionUtils.isEmpty(activityGoodsDOList)) {
                    for (ActivityGoodsDO activityGoodsDO : activityGoodsDOList) {
                        activityGoodsDO.setAuditStatus(ActivityGoodsAuditStatusEnum.AGREE.getCode());
                    }
                    goodsRepository.saveAll(activityGoodsDOList);
                }
            }

            /*22.1.20版废弃
            //外部流转记录
            activityRecordService.saveMerchantActivityOuterRecord(loginUser, merchantActivityDO.getId(),
                    outerResult.getData().getStatus(), outerResult.getData().getStatusDesc(),
                    outerResult.getData().getProperties().getOrDefault("oper", ""), "");*/
        }
    }

    /**
     * 待审核营销活动 (一级) - 审核
     * @param loginUser 登录用户信息
     * @param merchantActivityDOList 商家活动
     * @param agree 是否审核通过
     * @param opinion 审核意见
     */
    protected void baseExamineStep1Update(UserLoginCacheDTO loginUser, List<MerchantActivityDO> merchantActivityDOList, Integer agree, String opinion) {
        for (MerchantActivityDO merchantActivityDO : merchantActivityDOList) {
            // 执行内部流转
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(merchantActivityDO.getInnerProcessKey());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setDataId(merchantActivityDO.getId());
            executeVO.setAgree(agree);
            executeVO.setTaskId(merchantActivityDO.getInnerTaskId());
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }
            merchantActivityDO.setInnerTaskId(result.getData().getTaskId());
            merchantActivityDO.setInnerTaskStep(result.getData().getStep());
            merchantActivityDO.setInnerStatus(result.getData().getStatus());
            merchantActivityRepository.saveAndFlush(merchantActivityDO);

            // 内部流转记录
            activityRecordService.saveMerchantActivityInnerRecord(loginUser, merchantActivityDO.getId(),
                    result.getData().getStatus(), MerchantActivityInnerStatusEnum.getMessage(result.getData().getStatus()),
                    ActivityStrOperateEnum.mc_inner_examine_step1.getMessage(), opinion);
        }
    }

    /**
     * 待审核营销活动 (二级) - 审核
     * @param loginUser 登录用户信息
     * @param merchantActivityDOList 商家活动
     * @param agree 是否审核通过
     * @param opinion 审核意见
     */
    protected void baseExamineStep2Update(UserLoginCacheDTO loginUser, List<MerchantActivityDO> merchantActivityDOList, Integer agree, String opinion) {
        for (MerchantActivityDO merchantActivityDO : merchantActivityDOList) {
            // 执行内部流转
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(merchantActivityDO.getInnerProcessKey());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setDataId(merchantActivityDO.getId());
            executeVO.setAgree(agree);
            executeVO.setTaskId(merchantActivityDO.getInnerTaskId());
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }
            merchantActivityDO.setInnerTaskId(result.getData().getTaskId());
            merchantActivityDO.setInnerTaskStep(result.getData().getStep());
            merchantActivityDO.setInnerStatus(result.getData().getStatus());
            merchantActivityRepository.saveAndFlush(merchantActivityDO);

            // 内部流转记录
            activityRecordService.saveMerchantActivityInnerRecord(loginUser, merchantActivityDO.getId(),
                    result.getData().getStatus(), MerchantActivityInnerStatusEnum.getMessage(result.getData().getStatus()),
                    ActivityStrOperateEnum.mc_inner_examine_step1.getMessage(), opinion);
        }
    }
}